package com.atguigu.gmall.item.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.product.ProductSkuDetailFeignClient;
import com.atguigu.gmall.feign.search.SearchFeignClient;
import com.atguigu.gmall.item.service.SkuDetailService;
import com.atguigu.gmall.product.pojo.SkuImage;
import com.atguigu.gmall.product.pojo.SkuInfo;
import com.atguigu.gmall.product.pojo.SpuSaleAttr;
import com.atguigu.gmall.product.vo.CategoryTreeVo;
import com.atguigu.gmall.product.vo.SkuDetailVo;
import com.atguigu.gmall.starter.cache.aspect.annotation.MallCache;
import com.atguigu.gmall.starter.cache.service.CacheService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

@Service
@Slf4j
public class SkuDetailServiceImpl implements SkuDetailService {
    @Autowired
    ProductSkuDetailFeignClient productSkuDetailFeignClient;

    @Autowired
    SearchFeignClient searchFeignClient;

    @Autowired
    ThreadPoolExecutor executor;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    CacheService cacheService;

    @Autowired
    RedissonClient redissonClient;

//    static ReentrantLock lock = new ReentrantLock();



    @Override
    public SkuDetailVo getSkuDetails(Long skuId) {
        // 1.查看缓存内是否有存
        String skuDetailVoJson = redisTemplate.opsForValue().get(RedisConst.SKU_DETAIL_CACHE + skuId.toString());

        if (StringUtils.isEmpty(skuDetailVoJson)){
            // 缓存中不存在
            SkuDetailVo skuDetailVo = getSkuDetailVo(skuId);
            redisTemplate.opsForValue().set(skuId.toString(), JSON.toJSONString(skuDetailVo));
            log.info("新建查询"+skuId);
            return skuDetailVo;
        }else {
            log.info("缓存命中"+skuId);
            SkuDetailVo skuDetailVo = JSON.parseObject(skuDetailVoJson, SkuDetailVo.class);
            return skuDetailVo;
        }
    }

    @Override
    @MallCache(
//            cacheKey = RedisConst.SKU_DETAIL_CACHE + "#{#args[0]}",
//            bitMapName = RedisConst.SKU_IDS_BITMAP,
//            bitMapKey = "#{#args[0]}",
//            lockKey = "lock:sku:#{#args[0]}",
//            ttl = 30,
//            unit = TimeUnit.SECONDS
    )
    public SkuDetailVo getSkuDetailData(Long skuId) {
        SkuDetailVo skuDetailVo = this.getSkuDetailVo(skuId);
        return skuDetailVo;
    }

    @Override
    public void incrHotScore(Long skuId) {
        Long increment = redisTemplate.opsForValue().increment("sku:hotscore:" + skuId);

        if (increment % 100 == 0){
            searchFeignClient.updateHotScore(skuId,increment);
        }
    }


//    public SkuDetailVo getSkuDetailDataWithDistrLock(Long skuId) {
//        SkuDetailVo skuDetailVo = null;
//        // 1. 查询缓存。
//         skuDetailVo = cacheService.getForCache(methodAnnotation.bitMapName());
//
//        if (skuDetailVo == null){
//            log.info("开始查询位图是否存在");
//            Boolean contain = cacheService.mightContain(RedisConst.SKU_IDS_BITMAP, skuId);
//            if (!contain){
//                log.info("位图中没有，可能攻击请求，退回");
//                return null;
//            }else {
//                log.info("位图中有，进行回原");
//                log.info("开始抢锁");
//                RLock clientLock = redissonClient.getLock(RedisConst.SKU + skuId);
////                boolean tryLock = lock.tryLock();
//                boolean tryLock = clientLock.tryLock();
//                if (tryLock){
//                    log.info("抢锁成功，正在数据查询并上传到数据库");
//                    skuDetailVo = this.getSkuDetailVo(skuId);
//                    cacheService.saveData(skuId,skuDetailVo);
//                    log.info("完成数据查询并上传到数据库，并释放锁");
//                    clientLock.unlock();
//                }else {
//                    try {
//                        log.info("加锁失败等待500ms查询");
//                        TimeUnit.MILLISECONDS.sleep(500);
//                        skuDetailVo = cacheService.getForCache(methodAnnotation.bitMapName());
//                    } catch (InterruptedException e) {
//                        throw new RuntimeException(e);
//                    }
//                }
//            }
//        }
//
//        return skuDetailVo;
//    }

    /**
     * @param skuId
     * @return
     */
  /*@Override
    public SkuDetailVo getSkuDetailData(Long skuId){
        SkuDetailVo skuDetailVo = new SkuDetailVo();
        return skuDetailVo;
    }*/

    private SkuDetailVo getSkuDetailVo(Long skuId) {
        SkuDetailVo skuDetailVo = new SkuDetailVo();
        CompletableFuture<SkuInfo> skuInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            return productSkuDetailFeignClient.getSkuInfo(skuId).getData();
        },executor);

        //  商品详情
        CompletableFuture<Void> imageFuture = skuInfoCompletableFuture.thenAcceptAsync((skuInfo) -> {
            List<SkuImage> skuImages = productSkuDetailFeignClient.getSkuImages(skuId).getData();
            skuInfo.setSkuImageList(skuImages);
            skuDetailVo.setSkuInfo(skuInfo);
        }, executor);

        // :精确的分类路径
        CompletableFuture<Void> categoryFuture = skuInfoCompletableFuture.thenAcceptAsync((skuInfo) -> {
            CategoryTreeVo categoryTreeVo = productSkuDetailFeignClient.getCateGoryTreeWithC3id(skuInfo.getCategory3Id()).getData();
            SkuDetailVo.CategoryViewDTO categoryViewDTO = new SkuDetailVo.CategoryViewDTO();
            categoryViewDTO.setCategory1Id(categoryTreeVo.getCategoryId());
            categoryViewDTO.setCategory1Name(categoryTreeVo.getCategoryName());
            categoryViewDTO.setCategory2Id(categoryTreeVo.getCategoryChild().get(0).getCategoryId());
            categoryViewDTO.setCategory2Name(categoryTreeVo.getCategoryChild().get(0).getCategoryName());
            categoryViewDTO.setCategory3Id(categoryTreeVo.getCategoryChild().get(0).getCategoryChild().get(0).getCategoryId());
            categoryViewDTO.setCategory3Name(categoryTreeVo.getCategoryChild().get(0).getCategoryChild().get(0).getCategoryName());
            skuDetailVo.setCategoryView(categoryViewDTO);
        }, executor);

        CompletableFuture<Void> priceFuture = CompletableFuture.runAsync(
                () -> {
                    BigDecimal price = productSkuDetailFeignClient.getPrice(skuId).getData();
                    // ：实时价格
                    skuDetailVo.setPrice(price);
                }, executor);

        // 销售属性
        CompletableFuture<Void> saleAttrFuture = skuInfoCompletableFuture.thenAcceptAsync((skuInfo) -> {
            List<SpuSaleAttr> spuSaleAttrs = productSkuDetailFeignClient.getSpuSaleAttr(skuInfo.getSpuId(), skuId).getData();
            skuDetailVo.setSpuSaleAttrList(spuSaleAttrs);
        }, executor);

        CompletableFuture<Void> valueJsonFuture = skuInfoCompletableFuture.thenAcceptAsync((skuInfo) -> {
            String valuesSkuJson = productSkuDetailFeignClient.getValuesSkuJson(skuInfo.getSpuId()).getData();
            // ： Json
            skuDetailVo.setValuesSkuJson(valuesSkuJson);
        }, executor);

        CompletableFuture
                .allOf(valueJsonFuture,saleAttrFuture,priceFuture,categoryFuture,imageFuture)
                .join();
        return skuDetailVo;
    }
}
